package at.fhj.pse.datasource.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;

import at.fhj.pse.datasource.TimeIntervalDAO;
import at.fhj.pse.datasource.exception.DatasourceLayerException;
import at.fhj.pse.datasource.model.Activity;
import at.fhj.pse.datasource.model.TimeInterval;

public class TimeIntervalDAOImpl implements TimeIntervalDAO, Serializable {

	private static final long serialVersionUID = -1165128854736674764L;

	private final Logger LOG = Logger.getLogger(TimeIntervalDAOImpl.class
			.getName());

	// see META-INF/persistence.xml for persistence unit configuration
	@Inject
	private EntityManager em;

	@Override
	public void saveTimeInterval(TimeInterval timeInterval) {
		if (timeInterval == null) {
			throw new DatasourceLayerException("timeInterval is null", new IllegalArgumentException());
		}
		LOG.info("save Interval(" + timeInterval.getFrom().toString() + " - "
				+ timeInterval.getTo().toString() + ")");
		em.persist(timeInterval);
		em.flush();
	}

	@Override
	public List<TimeInterval> getTimeIntervalByDayAndUsername(
			Date dayOfIntervals, String username) {
		if (dayOfIntervals == null) {
			throw new DatasourceLayerException("dayOfIntervals is null", new IllegalArgumentException());
		}
		if (username == null) {
			throw new DatasourceLayerException("username is null", new IllegalArgumentException());
		}
		List<TimeInterval> intervals = new ArrayList<TimeInterval>();
		TypedQuery<TimeInterval> query = this.em
				.createQuery(
						"Select t FROM Employee e INNER JOIN e.timeIntervals t INNER JOIN FETCH t.activity a "
								+ "WHERE e.username LIKE :username AND date(t.from_Date) = :date AND date(t.to_Date) = :date ORDER BY t.from_Date",
						TimeInterval.class).setParameter("username", username)
				.setParameter("date", dayOfIntervals, TemporalType.DATE);
		intervals = query.getResultList();
		return intervals;
	}

	@Override
	public List<TimeInterval> getTimeIntervalByMonthAndYearAndUsername(
			int month, int year, String username) {
		if (username == null) {
			throw new DatasourceLayerException("username is null", new IllegalArgumentException());
		}
		List<TimeInterval> intervals = new ArrayList<TimeInterval>();
		TypedQuery<TimeInterval> query = this.em
				.createQuery(
						"Select t FROM Employee e INNER JOIN e.timeIntervals t INNER JOIN FETCH t.activity a "
								+ "WHERE e.username LIKE :username AND year(t.from_Date) = :year AND month(t.from_Date) = :month ORDER BY t.from_Date",
						TimeInterval.class).setParameter("username", username)
				.setParameter("year", year).setParameter("month", month);
		intervals = query.getResultList();
		return intervals;
	}

	@Override
	public List<TimeInterval> getTimeIntervalByEmployeeID(long employeeID) {
		List<TimeInterval> intervals = new ArrayList<TimeInterval>();
		intervals = (List<TimeInterval>) this.em
				.createQuery(
						"SELECT t FROM TimeInterval t INNER JOIN FETCH t.activity a WHERE employee_id = :userid ORDER BY t.from_Date DESC",
						TimeInterval.class).setParameter("userid", employeeID)
				.getResultList();
		return intervals;
	}

	@Override
	public void deleteTimeIntervalById(long interval_id) {
		this.em.createQuery("DELETE FROM TimeInterval WHERE id = :interval_id")
				.setParameter("interval_id", interval_id).executeUpdate();

	}

	@Override
	public List<TimeInterval> getTimeIntervalByActivityAndDatesAndUsername(
			Activity tiActivity, Date from_Date, Date to_Date, String username) {
		if (tiActivity == null) {
			throw new DatasourceLayerException("tiActivity is null", new IllegalArgumentException());
		}
		if (from_Date == null) {
			throw new DatasourceLayerException("from_Date is null", new IllegalArgumentException());
		}
		if (to_Date == null) {
			throw new DatasourceLayerException("to_Date is null", new IllegalArgumentException());
		}
		if (username == null) {
			throw new DatasourceLayerException("username is null", new IllegalArgumentException());
		}
		List<TimeInterval> intervals = new ArrayList<TimeInterval>();
		TypedQuery<TimeInterval> query = this.em
				.createQuery(
						"Select t FROM Employee e INNER JOIN e.timeIntervals t INNER JOIN FETCH t.activity a "
								+ "WHERE e.username LIKE :username AND date(t.from_Date) >= :from_date AND date(t.to_Date) <= :to_date AND a.id LIKE :activity ORDER BY t.from_Date",
						TimeInterval.class).setParameter("username", username)
				.setParameter("from_date", from_Date, TemporalType.DATE)
				.setParameter("to_date", to_Date, TemporalType.DATE)
				.setParameter("activity", tiActivity.getId());
		intervals = query.getResultList();
		return intervals;
	}

	@Override
	public List<TimeInterval> getTimeIntervalByDatesAndUsername(Date from_Date,
			Date to_Date, String username) {
		if (from_Date == null) {
			throw new DatasourceLayerException("from_Date is null", new IllegalArgumentException());
		}
		if (to_Date == null) {
			throw new DatasourceLayerException("to_Date is null", new IllegalArgumentException());
		}
		if (username == null) {
			throw new DatasourceLayerException("username is null", new IllegalArgumentException());
		}
		List<TimeInterval> intervals = new ArrayList<TimeInterval>();
		TypedQuery<TimeInterval> query = this.em
				.createQuery(
						"Select t FROM Employee e INNER JOIN e.timeIntervals t INNER JOIN FETCH t.activity a "
								+ "WHERE e.username LIKE :username AND date(t.from_Date) >= :from_date AND date(t.to_Date) <= :to_date ORDER BY t.from_Date",
						TimeInterval.class).setParameter("username", username)
				.setParameter("from_date", from_Date, TemporalType.DATE)
				.setParameter("to_date", to_Date, TemporalType.DATE);
		intervals = query.getResultList();
		return intervals;
	}

}
